package com.xinz.protocal.server;

import java.lang.reflect.InvocationTargetException;

import com.xinz.protocal.Buffer;
import com.xinz.protocal.ErrorHandler;
import com.xinz.protocal.NativeInvokeFilter;
import com.xinz.protocal.Serializer;
import com.xinz.protocal.ServiceException;
import com.xinz.protocal.Session;
import com.xinz.protocal.config.ConfigFactory;

/***
 * 远程调用层  RemoteInvoker
 * 序列化层  Serializer
 * 传输层 InvokConnector
 * 
 * 传输层 Connector?
 * 序列化层  Serializer
 * 本地调用层 NativeInvoker
 * 序列化层  Serializer
 * 传输层 Connector?
 * 
 * 传输层 InvokConnector
 * 序列化层  Serializer
 * 远程调用层  RemoteInvoker
 * @author xingyun
 *
 */
public class NativeInvoker {

	ConfigFactory factory;
	
	public NativeInvoker(ConfigFactory factory) {
		this.factory = factory;
	}
	
	public Buffer invoke(Session session, Buffer request) {
		Session.setCurrent(session);
		
		try {
			// 调用序列化层，把方法调用的细节序列化层字节数组
			ResponseHeaderProvider headerProvider = factory.getNativeConfig().getResponseHeaderProvider();
			Serializer serializer = factory.getShareConfig().getSerializer();
			ErrorHandler handler = factory.getNativeConfig().getErrorHandler();
			NativeInvokeFilter filter = factory.getNativeConfig().getNativeInvokeFilter();
			NativeMethod method = serializer.parseMethod(session, request);
			
			Object result = null;
			boolean isException = false;
			
			try {
				if(method == null) {
					result = handler.interfaceNotFind(method);
				}
				else {
					Object obj = session.findImplement(method.getMethod());
					if(obj == null) {
						result =  handler.implementerNotFind(method);
					}
					else {
						// 最终调用本地实现
						filter.readyInvoke(method);
						try {
							result = method.invoke(obj);
						}
						catch(InvocationTargetException e) {
							throw filter.invokeException(method, e);
						}
						filter.invokeSuccess(method);
						session.setTag("method_name", method.getMethod().getName());
					}
				}
			}
			catch(InvocationTargetException e) {
				Throwable targetException = e.getTargetException();
				targetException.printStackTrace();
				if(targetException instanceof ServiceException) {
					result = targetException;
				}
				else {
					result = new ServiceException("服务异常，请稍后再试：" + targetException);
				}
				isException = true;
			}
			catch(ServiceException e) {
				result = e;
				isException = true;
				e.printStackTrace();
			}
			catch(Exception e) {
				result = new ServiceException("系统异常，请稍后再试：" + e);
				isException = true;
				e.printStackTrace();
			}
			
			Object responseHeader = null;
			try {
				responseHeader = headerProvider.provideResponseHeader(session, method.getMethod(), method.getRequestHeader(), method.getArgs(), isException, result);
			}
			catch(ServiceException e) {
				//抓取ServiceException，直接抛到客户端
				result = e;
				isException = true;
				e.printStackTrace();
			}
			catch (Exception e) {
				//其他异常则包装成ServiceException然后发到客户端
				result = new ServiceException("服务器返回头异常，请稍后再试:"+e);
				isException = true;
				e.printStackTrace();
			}
			
			try{
				// 解析返回结果，如果有异常则直接在解析层抛出
				return serializer.returnToBuffer(session, responseHeader,result, isException);
			}
			finally{
				
			}
		}
		finally {
			Session.setCurrent(null);
		}
	}
}
